Source code for hysop.operator.diffusion

# Copyright (c) HySoP 2011-2024
#
# This file is part of HySoP software.
# See "https://particle_methods.gricad-pages.univ-grenoble-alpes.fr/hysop-doc/"
# for further info.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""
@file diffusion.py
Diffusion operator generator.
"""
from hysop.constants import Implementation, HYSOP_REAL
from hysop.tools.htypes import check_instance, first_not_None
from hysop.tools.henum import EnumFactory
from hysop.tools.decorators import debug
from hysop.fields.continuous_field import Field
from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors
from hysop.parameters.scalar_parameter import ScalarParameter

from hysop.operator.base.spectral_operator import SpectralComputationalGraphNodeFrontend
from hysop.backend.host.python.operator.diffusion import PythonDiffusion

try:
    from hysop.backend.device.opencl.operator.diffusion import OpenClDiffusion
except ImportError:
    OpenClDiffusion = None
try:
    from hysop.backend.host.fortran.operator.diffusion import DiffusionFFTW
except ImportError:
    DiffusionFFTW = None


[docs] class Diffusion(SpectralComputationalGraphNodeFrontend): """ Interface the diffusion solver. Available implementations are: FORTRAN: FFTW based solver (legacy fortran) PYTHON: generic python fft based solver (pyfftw, scipy or numpy) OPENCL: generic opencl fft based solver (gpyfft) """
[docs] @classmethod def implementations(cls): __implementations = { Implementation.PYTHON: PythonDiffusion, } if not OpenClDiffusion is None: __implementations.update( { Implementation.OPENCL: OpenClDiffusion, } ) if not DiffusionFFTW is None: __implementations.update( { Implementation.FORTRAN: DiffusionFFTW, } ) return __implementations
[docs] @classmethod def default_implementation(cls): return Implementation.PYTHON
@debug def __new__( cls, Fin, variables, nu, dt, Fout=None, implementation=None, base_kwds=None, **kwds, ): base_kwds = first_not_None(base_kwds, {}) return super().__new__( cls, Fin=Fin, Fout=Fout, variables=variables, nu=nu, dt=dt, implementation=implementation, base_kwds=base_kwds, **kwds, ) @debug def __init__( self, Fin, variables, nu, dt, Fout=None, implementation=None, base_kwds=None, **kwds, ): """ Initialize a Poisson operator frontend. Solves dF/dt = nu * Laplacian(F) Parameters ---------- Fin: field input field that should be diffused Fout: field, optional, defaults to none output field that should be diffused. if None this will be set to Fin. variables: dict dictionary of fields as keys and topologies as values. nu: float or ScalarParameter Some implementations may only offer scalar nu. dt: ScalarParameter Timestep parameter that will be used for time integration. implementation: Implementation, optional, defaults to None target implementation, should be contained in available_implementations(). If None, implementation will be set to default_implementation(). base_kwds: dict, optional, defaults to None Base class keywords arguments. If None, an empty dict will be passed. kwds: Keywords arguments that will be passed towards implementation poisson operator __init__. Notes ----- A diffusion operator implementation should at least support the hysop.operator.base.diffusion.DiffusionBase interface. """ Fout = first_not_None(Fout, Fin) base_kwds = first_not_None(base_kwds, {}) check_instance(Fin, Field) check_instance(Fout, Field) check_instance(variables, dict, keys=Field, values=CartesianTopologyDescriptors) check_instance(base_kwds, dict, keys=str) check_instance(dt, ScalarParameter) check_instance(nu, (float, ScalarParameter)) if not isinstance(nu, ScalarParameter): nu = ScalarParameter( name="nu", dtype=HYSOP_REAL, initial_value=nu, quiet=True ) super().__init__( Fin=Fin, Fout=Fout, variables=variables, nu=nu, dt=dt, implementation=implementation, base_kwds=base_kwds, **kwds, )